//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "LigandEpitopeDataLINGO.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LINGOLENGTH 4
#define LENGTHLINE  10000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
namespace LigandEpitopeSpace {
  
  bool EqualLingo (TNode <String>* ligand, void* ref) {

    return (!strcmp(ligand->Info()->Out(), (char*)ref))?true:false;

  }
  
};
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
LigandEpitopeDataLINGO::LigandEpitopeDataLINGO (): LigandEpitopeData(), 
                                                   metaStructureAligment(0) {
  
  this->smiles1      = new String ();
  this->smiles2      = new String ();
  this->epitope1     = new String ();
  this->epitope2     = new String ();
  
  this->commonLingos = new TListE <String> ();
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
LigandEpitopeDataLINGO::LigandEpitopeDataLINGO (const LigandEpitopeDataLINGO& ligandEpitopeDataLINGO): LigandEpitopeData(ligandEpitopeDataLINGO),
                                                                                                       metaStructureAligment(ligandEpitopeDataLINGO.metaStructureAligment) {
  
  this->smiles1      = new String (ligandEpitopeDataLINGO.smiles1);
  this->smiles2      = new String (ligandEpitopeDataLINGO.smiles2);
  this->epitope1     = new String (ligandEpitopeDataLINGO.epitope1);
  this->epitope2     = new String (ligandEpitopeDataLINGO.epitope2);
  
  this->commonLingos = new TListE <String> (ligandEpitopeDataLINGO.commonLingos);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
LigandEpitopeDataLINGO::LigandEpitopeDataLINGO (const LigandEpitopeDataLINGO* ligandEpitopeDataLINGO): LigandEpitopeData(ligandEpitopeDataLINGO),
                                                                                                       metaStructureAligment(ligandEpitopeDataLINGO->metaStructureAligment) {
  
  this->smiles1      = new String (ligandEpitopeDataLINGO->smiles1);
  this->smiles2      = new String (ligandEpitopeDataLINGO->smiles2);
  this->epitope1     = new String (ligandEpitopeDataLINGO->epitope1);
  this->epitope2     = new String (ligandEpitopeDataLINGO->epitope2);
  
  this->commonLingos = new TListE <String> (ligandEpitopeDataLINGO->commonLingos);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
LigandEpitopeDataLINGO::~LigandEpitopeDataLINGO () {
  
  if (this->smiles1)      delete this->smiles1;
  if (this->smiles2)      delete this->smiles2;
  if (this->epitope1)     delete this->epitope1;
  if (this->epitope2)     delete this->epitope2;
  
  if (this->commonLingos) delete this->commonLingos;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void LigandEpitopeDataLINGO::Smiles1 (String* smiles1) {
  
  if (smiles1) this->smiles1->In(smiles1);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void LigandEpitopeDataLINGO::Smiles2 (String* smiles2) {
  
  if (smiles2) this->smiles2->In(smiles2);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void LigandEpitopeDataLINGO::Epitope1 (String* epitope1) {
  
  if (epitope1) this->epitope1->In(epitope1);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void LigandEpitopeDataLINGO::Epitope2 (String* epitope2) {
  
  if (epitope2) this->epitope2->In(epitope2);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void LigandEpitopeDataLINGO::MetaStructureAligment (double metaStructureAligment) {
  
  if (metaStructureAligment >= 0) this->metaStructureAligment = metaStructureAligment;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void LigandEpitopeDataLINGO::CommonLingos(TListE<String>* commonLingos) {
  
  if (commonLingos) *(this->commonLingos) = *(commonLingos);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* LigandEpitopeDataLINGO::Smiles1 (void) {
  
  return this->smiles1;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* LigandEpitopeDataLINGO::Smiles2 (void) {
  
  return this->smiles2;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* LigandEpitopeDataLINGO::Epitope1 (void) {
  
  return this->epitope1;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* LigandEpitopeDataLINGO::Epitope2 (void) {
  
  return this->epitope2;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
double LigandEpitopeDataLINGO::MetaStructureAligment (void) {
  
  return this->metaStructureAligment;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* LigandEpitopeDataLINGO::CommonLingos (void) {
  
  return this->commonLingos;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool LigandEpitopeDataLINGO::LoadData (char* data) {
  
  if (!data || !strlen(data)) return false;
  
  char* parts = NULL;
  
  parts = strtok(data, " \n\r\t");
  if (parts) this->ligandName1->In(parts);
  else       return false;
    
  parts = strtok(NULL, " \n\r\t");
  if (parts) this->ligandName2->In(parts);
  else       return false;
  
  parts = strtok(NULL, " \n\r\t");
  if (parts) this->lingoSimValue = atol(parts);
  else       return false;
  
  parts = strtok(NULL, " \n\r\t");
  if (parts) this->metaStructureAligment = atol(parts);
  else       return false;
  
  parts = strtok(NULL, " \n\r\t");
  if (parts) this->domain1->In(parts + 1);
  else       return false;
  
  parts = strtok(NULL, " \n\r\t");
  if (parts) this->domain2->In(parts + 1);
  else       return false;
  
  parts = strtok(NULL, " \n\r\t");
  if (parts) this->epitope1->In(parts);
  else       return false;
  
  parts = strtok(NULL, " \n\r\t");
  if (parts) this->epitope2->In(parts);
  else       return false;
  
  this->commonLingos->Clear();
  
  parts = strtok(NULL, " \n\r\t");
  while (parts) {
    this->commonLingos->Add(new String(parts));
    parts = strtok(NULL, " \n\r\t");
  }
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool LigandEpitopeDataLINGO::LoadData (String* data) {
  
  if (!data || !data->Length()) return false;
  
  return this->LoadData(data->Out());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool LigandEpitopeDataLINGO::LoadDataWithoutLingos (char* data) {
  
  if (!data || !strlen(data)) return false;
  
  char ligandN1  [4];
  char ligandN2  [4];
  char domainN1  [8];
  char domainN2  [8];
  char epitopeN1 [84];
  char epitopeN2 [84];
  
  sscanf (data, "%s %s %lf %lf >%s >%s %s %s %*s", ligandN1, 
                                                   ligandN2, 
                                                   &(this->lingoSimValue),
                                                   &(this->metaStructureAligment),
                                                   domainN1,
                                                   domainN2,
                                                   epitopeN1,
                                                   epitopeN2);
  
  if (ligandN1)  this->ligandName1->In(ligandN1);
  if (ligandN2)  this->ligandName2->In(ligandN2);
  if (domainN1)  this->domain1->In(domainN1);
  if (domainN2)  this->domain2->In(domainN2);
  if (epitopeN1) this->epitope1->In(epitopeN1);
  if (epitopeN2) this->epitope2->In(epitopeN2);
  
  this->ligandName1->RTrim();
  this->ligandName2->RTrim();
  this->domain1->RTrim();
  this->domain2->RTrim();
  this->epitope1->RTrim();
  this->epitope2->RTrim();
  
  this->commonLingos->Clear();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool LigandEpitopeDataLINGO::LoadDataWithoutLingos (String* data) {
  
  if (!data || !data->Length()) return false;
  
  return this->LoadDataWithoutLingoSim(data->Out());
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* LigandEpitopeDataLINGO::ToString (void) {
  
  this->toString->In("");
  
  char data [LENGTHLINE]; 
  
  this->ligandName1->RTrim();
  this->ligandName2->RTrim();
  this->domain1->RTrim();
  this->domain2->RTrim();
  this->epitope1->RTrim();
  this->epitope2->RTrim();
  
  sprintf (data, "%5s %5s %5d %5d >%s >%s %s %s\0", this->ligandName1->Out(), 
                                                    this->ligandName2->Out(), 
                                                    (int)this->lingoSimValue,
                                                    (int)this->metaStructureAligment,
                                                    this->domain1->Out(),
                                                    this->domain2->Out(),
                                                    this->epitope1->Out(),
                                                    this->epitope2->Out());
  
  this->toString->Add(data);
  
  this->commonLingos->SetInitial();
  while (this->commonLingos->SetNext()) {
    this->toString->Add(" ");
    this->toString->Add(this->commonLingos->GetCurrent());
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool LigandEpitopeDataLINGO::GetCommonLingos (void) {

  if (!this->smiles1 || (this->smiles1->Length() < LINGOLENGTH) || !this->smiles2 || (this->smiles2->Length() < LINGOLENGTH))
    return false;

  char tmpLingo [LINGOLENGTH + 1];
  
  for (int i = 0; i <= this->smiles1->Length() - LINGOLENGTH; i++) {
    
    strncpy(tmpLingo, this->smiles1->Out() + i, LINGOLENGTH);
    tmpLingo[LINGOLENGTH] = '\0';
    
    if (strstr(this->smiles2->Out(), tmpLingo) && (!(this->commonLingos->FirstOcurrence(LigandEpitopeSpace::EqualLingo, tmpLingo))))
      this->commonLingos->Add(new String (tmpLingo));
    
  }

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
LigandEpitopeDataLINGO LigandEpitopeDataLINGO::operator= (const LigandEpitopeDataLINGO& ligandEpitopeDataLINGO) {
  
  this->smiles1->In(ligandEpitopeDataLINGO.smiles1);
  this->smiles2->In(ligandEpitopeDataLINGO.smiles2);
  this->ligandName1->In(ligandEpitopeDataLINGO.ligandName1);
  this->ligandName2->In(ligandEpitopeDataLINGO.ligandName2);
  this->domain1->In(ligandEpitopeDataLINGO.domain1);
  this->domain2->In(ligandEpitopeDataLINGO.domain2);
  this->epitope1->In(ligandEpitopeDataLINGO.epitope1);
  this->epitope2->In(ligandEpitopeDataLINGO.epitope2);
  
  this->ligandNumber1         = ligandEpitopeDataLINGO.ligandNumber1;
  this->ligandNumber2         = ligandEpitopeDataLINGO.ligandNumber2;
  this->secondaryStructureMT  = ligandEpitopeDataLINGO.secondaryStructureMT;
  this->compactnessMT         = ligandEpitopeDataLINGO.compactnessMT;
  this->lingoSimValue         = ligandEpitopeDataLINGO.lingoSimValue;
  this->metaStructureAligment = ligandEpitopeDataLINGO.metaStructureAligment;
  
  *(this->commonLingos)       = *(ligandEpitopeDataLINGO.commonLingos); 
  
  return *this;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
